/* @flow */

import type Watcher from './watcher'
import {remove} from '../util/index'
import config from '../config'

let uid = 0

/**
 * A dep is an observable that can have multiple
 * directives subscribing to it.
 */
/*
*
* 一个dep对应一个obj.key
* 在读取响应式数据时，负责收集依赖，每个dep（或者说obj.key）依赖的watcher有哪些
* 在响应式数据更新时，负责通知dep中那些watcher去执行update方法
*
* */
export default class Dep {
  static target: ?Watcher;
  id: number;
  subs: Array<Watcher>;

  constructor() {
    this.id = uid++
    this.subs = []
  }

  // 在dep中添加watcher
  addSub(sub: Watcher) {
    this.subs.push(sub)
  }

  removeSub(sub: Watcher) {
    remove(this.subs, sub)
  }

  // 向watcher中添加dep
  depend() {
    if (Dep.target) {
      Dep.target.addDep(this)
    }
  }

  // 通知dep中所有的watcher，执行watcher.update()方法
  notify() {
    // stabilize the subscriber list first
    const subs = this.subs.slice()
    if (process.env.NODE_ENV !== 'production' && !config.async) {
      // subs aren't sorted in scheduler if not running async
      // we need to sort them now to make sure they fire in correct
      // order
      subs.sort((a, b) => a.id - b.id)
    }

    // 遍历dep中存储的watcher，执行watcher.update()
    for (let i = 0, l = subs.length; i < l; i++) {
      subs[i].update()
    }
  }
}

// The current target watcher being evaluated.
// This is globally unique because only one watcher
// can be evaluated at a time.
// 当前正在执行的watcher，同一时间只会有一个watcher在执行
// Dep.target为当前执行的watcher
// 通过调用pushTarget方法完成赋值，调用popTarget方法完成重置（null）
Dep.target = null
const targetStack = []

// 在需要进行依赖收集的时候调用，设置Dep.target = watcher
export function pushTarget(target: ?Watcher) {
  targetStack.push(target)
  Dep.target = target
}

// 依赖收集结束调用，设置Dep.target = null
export function popTarget() {
  targetStack.pop()
  Dep.target = targetStack[targetStack.length - 1]
}
